(function() {
	"use strict";
	/**
	 * (en)scatterDirective
	 * @ko scatterDirective
	 * @group Directive
	 * @name scatterDirective
	 * @class
	 */
	pinpointApp.constant("scatterDirectiveConfig", {
		"scatterDataUrl": "getScatterData.pinpoint",
		template: "<div id='scatter' style='padding-top:10px;padding-bottom:20px;user-select:none;'></div>",
		images: {
			"config": "",
			"download": "",
			"fullscreen": "",
			"error": ""
		},
		options: {
			"containerId": "",
			"containerClass": "bigscatterchart",
			"width": 400,
			"height": 250,
			"minX": 0, maxX: 1000,
			"minY": 0, maxY: 10000,
			"minZ": 0, maxZ: 5,
			"bubbleSize": 3,
			"labelX": "",
			"labelY": "(ms)",
			"realtime": false,
			"chartAnimationTime": 300,
			"gridAxisStyle": {
				"lineWidth": 1,
				"lineDash": [1, 0],
				"globalAlpha": 1,
				"strokeStyle" : "#e3e3e3"
			},
			"padding" : {
				"top": 40,
				"left": 50,
				"right": 40,
				"bottom": 30
			},
			"typeInfo": {
				/*[ typeName, typeColor, typeDisplayOrder ]*/
				"0": [ "Failed", "#d62728", 20],
				"1": ["Success", "#2ca02c", 10]
			},
			"propertyIndex": {
				"x": 0,
				"y": 1,
				"meta": 2,
				"transactionId": 3,
				"type": 4,
				"groupCount": 5
			},
			"checkBoxImage": {
				"checked" : "",
				"unchecked" : ""
			}
		}
	});

	pinpointApp.directive("scatterDirective", ["scatterDirectiveConfig", "$rootScope", "$compile", "$timeout", "webStorage", "$window", "$http", "UrlVoService", "CommonAjaxService", "TooltipService", "AnalyticsService", "PreferenceService",
		function ( cfg, $rootScope, $compile, $timeout, webStorage, $window, $http, UrlVoService, commonAjaxService, tooltipService, analyticsService, preferenceService ) {
			return {
				template: cfg.template,
				restrict: "EA",
				replace: true,
				scope: {
					namespace: "@"
				},
				link: function (scope, element, attrs) {
					var oNavbarVoService = null, htScatterSet = {}, htLastNode = null;
					var enableRealtime = attrs["enableRealtime"] == "true" ? true : false;

					function makeScatter(target, application, w, h, scatterData) {
						// var from = oNavbarVoService.getQueryStartTime();
						// var to = oNavbarVoService.getQueryEndTime();
						// var filter = oNavbarVoService.getFilter();
						var from = UrlVoService.getQueryStartTime();
						var to = UrlVoService.getQueryEndTime();
						var filter = UrlVoService.getFilter();
						var applicationName = application.split("^")[0];
						var options = {};
						angular.copy(cfg.options, options);
						options.sPrefix = "BigScatterChart2-" + parseInt( Math.random() * 100000 );
						options.containerId = target;
						options.width = w ? w : options.width;
						options.height = h ? h : options.height;
						options.minX = from;
						options.maxX = to;
						options.errorImage = cfg.images.error;
						// options.realtime = isRealtime();
						options.realtime = UrlVoService.isRealtime() && enableRealtime;

						var oScatterChart = new BigScatterChart2(options, getAgentList(scatterData), [
							new BigScatterChart2.SettingPlugin( cfg.images.config ).addCallback( function( oChart, oValue ) {
								webStorage.add( "scatter-y-min" + scope.namespace, oValue.min );
								webStorage.add( "scatter-y-max" + scope.namespace, oValue.max );
								oChart.changeRangeOfY( oValue );
								oChart.redraw();
							}),
							new BigScatterChart2.DownloadPlugin( cfg.images.download, "PNG" ).addCallback( function( oChart ) {
								analyticsService.send( analyticsService.CONST.MAIN, analyticsService.CONST.CLK_DOWNLOAD_SCATTER );
							}),
							new BigScatterChart2.WideOpenPlugin( cfg.images.fullscreen ).addCallback( function() {
								// var partialURL = oNavbarVoService.isRealtime() ? "realtime/" + oNavbarVoService.getQueryEndDateTime() : oNavbarVoService.getPartialURL( false, true );
								var partialURL = UrlVoService.isRealtime() && enableRealtime ? "realtime/" + UrlVoService.getQueryEndDateTime() : UrlVoService.getPartialURL( false, true );
								$window.open( "#/scatterFullScreenMode/" + htLastNode.applicationName + "@" + htLastNode.serviceType + "/" + partialURL + "/" + getAgentList().join(","), "width=900, height=700, resizable=yes");
							}),
							new BigScatterChart2.HelpPlugin( tooltipService )
						], {
							sendAnalytics: function( type, bChecked ) {
								analyticsService.send( analyticsService.CONST.MAIN, analyticsService.CONST[type === "Success" ? "TG_SCATTER_SUCCESS" : "TG_SCATTER_FAILED"], analyticsService.CONST[bChecked ? "ON" : "OFF"] );
							},
							loadFromStorage: function( key ) {
								return webStorage.get( key + scope.namespace );
							},
							onSelect: function( oDragAreaPosition, oDragXY ) {
								if ( arguments.length === 5 ) {
									// $window.open("#/transactionList/" + oNavbarVoService.getPartialURL(true, false), application + "|" + arguments[0] + "|" + arguments[1] + "|" + arguments[2] + "|" + arguments[3] );
									$window.open("#/transactionList/" + UrlVoService.getPartialURL(true, false), application + "|" + arguments[0] + "|" + arguments[1] + "|" + arguments[2] + "|" + arguments[3] + "|" + arguments[4]  );
								} else {
									var token = application + "|" + oDragXY.fromX + "|" + oDragXY.toX + "|" + oDragXY.fromY + "|" + oDragXY.toY + "|" + arguments[2] + "|" + arguments[3];
									// $window.open("#/transactionList/" + oNavbarVoService.getPartialURL(true, false), token);
									$window.open("#/transactionList/" + UrlVoService.getPartialURL(true, false), token);
								}
							},
							onError: function() {

							}
						}, preferenceService.getAgentAllStr() );

						$timeout(function () {
							if (angular.isUndefined(scatterData)) {
								oScatterChart.drawWithDataSource( new BigScatterChart2.DataLoadManager( applicationName, filter, {
									"url": cfg.scatterDataUrl,
									"realtime": UrlVoService.isRealtime() && enableRealtime,
									"realtimeInterval": 2000,
									"realtimeDefaultTimeGap": 3000,
									"realtimeResetTimeGap": 20000,
									"fetchLimit": 5000,
									"fetchingInterval": 2000,
									"useIntervalForFetching": false
								}, function( oChartXRange, nextFrom, nextTo ) {
									// oNavbarVoService.setQueryEndDateTime( nextFrom );
									UrlVoService.setQueryEndDateTime( nextFrom );
									$rootScope.$broadcast( "nodeInfoDetailsDirective.loadRealTimeChartData", applicationName, oScatterChart.getCurrentAgent(), oChartXRange.min, oChartXRange.max );
								}));
							} else {
								oScatterChart.addBubbleAndMoveAndDraw( oScatterChart.createDataBlock( scatterData ) );
							}
							if ( attrs["namespace"] === "forMain" || attrs["namespace"] === "forFilteredMap" ) {
								$window.htoScatter[application] = oScatterChart;
							}
						}, 100);

						return oScatterChart;
					}
					function showScatter(application, w, h) {
						element.children().hide();
						pauseScatterAll();
						if ( angular.isDefined(htScatterSet[application]) ) {
							htScatterSet[application].target.show();
							if ( UrlVoService.isRealtime() && enableRealtime ) {
								commonAjaxService.getServerTime( function( serverTime ) {
									// serverTime -= 3000;
									htScatterSet[application].scatter.resume( serverTime - preferenceService.getRealtimeScatterXRange(), serverTime );
									htScatterSet[application].scatter.selectAgent( preferenceService.getAgentAllStr(), true);
								});
							} else {
								htScatterSet[application].scatter.resume();
								htScatterSet[application].scatter.selectAgent( preferenceService.getAgentAllStr(), true);
							}
						} else {
							makeNewScatter( application, w, h );
						}
					}
					function showScatterWithData(application, w, h, data) {
						if (angular.isDefined(htScatterSet[application])) {
							htScatterSet[application].scatter.addBubbleAndMoveAndDraw( htScatterSet[application].scatter.createDataBlock( data ) );
						} else {
							makeNewScatter(application, w, h, data);
							htScatterSet[application].target.hide();
						}
					}
					function makeNewScatter( application, w, h, data ) {
						var target = angular.element( cfg.template );
						var oScatter = makeScatter(target, application, w, h, data);
						htScatterSet[application] = {
							target : target,
							scatter : oScatter
						};
						element.append( target );
					}

					function showScatterBy(application) {
						element.children().hide();
						if (angular.isDefined(htScatterSet[application])) {
							htScatterSet[application].target.show();
							htScatterSet[application].scatter.selectAgent( preferenceService.getAgentAllStr(), true);
						}
					}


					function pauseScatterAll() {
						angular.forEach(htScatterSet, function (scatterSet, key) {
							scatterSet.scatter.pause();
						});
					}
					function initScatterHash() {
						for (var p in htScatterSet) {
							htScatterSet[p].scatter.abort();
						}
						htScatterSet = {};
					}
					function getAgentList( scatterData ) {
						var oDupCheck = {};
						var aAgentList = [];
						if ( typeof scatterData !== "undefined" ) {
							$.each( scatterData.scatter.metadata, function( key, oInfo ) {
								if ( typeof oDupCheck[ oInfo[0] ] === "undefined" ) {
									oDupCheck[ oInfo[0] ] = true;
									aAgentList.push( oInfo[0] );
								}
							});
							return aAgentList;
						}
						if ( htLastNode && htLastNode.agentIds ) {
							return htLastNode.agentIds;
						}
					}
					scope.$on("scatterDirective.initialize." + scope.namespace, function (event, navbarVoService) {
						// oNavbarVoService = navbarVoService;
						initScatterHash();
						element.empty();
					});
					scope.$on("scatterDirective.initializeWithNode." + scope.namespace, function (event, node, w, h) {
						scope.currentAgent = preferenceService.getAgentAllStr();
						htLastNode = node;
						showScatter(node.key, w, h);
					});
					scope.$on("scatterDirective.initializeWithData." + scope.namespace, function (event, application, data) {
						scope.currentAgent = preferenceService.getAgentAllStr();
						var aSplit = application.split("^");
						htLastNode = {
							applicationName: aSplit[0],
							serviceType: aSplit[1],
							key: application
						};
						showScatterWithData(application, null, null, data);
					});
					scope.$on("scatterDirective.showByNode." + scope.namespace, function (event, node) {
						htLastNode = node;
						showScatterBy(node.key);
					});
					scope.$on("responseTimeSummaryChartDirective.showErrorTransactionList." + scope.namespace, function( event, category ) {
						$window.htoScatter[htLastNode.key].selectType( "Failed" ).fireDragEvent({
							animate: function() {},
							css : function( name ) {
								return name === "left" ? cfg.options.padding.left + "px" : ( name === "top" ? cfg.options.padding.top + "px" : "0px" );
							},
							width: function() {
								return cfg.options.width - cfg.options.padding.left - cfg.options.padding.right;
							},
							height: function() {
								return cfg.options.height - cfg.options.padding.top - cfg.options.padding.bottom;
							}
						});
					});
					scope.$on("changedCurrentAgent." + scope.namespace, function( event, selectedAgentName ) {
						if ( htLastNode && htLastNode.key ) {
							htScatterSet[htLastNode.key].scatter.selectAgent(selectedAgentName);
						}
					});
					scope.$on("scatterDirective.stopRequest." + scope.namespace, function( event ) {
						pauseScatterAll();
					});
				}
			};
		}
	]);
})();